package org.koin.core.registry;

import org.koin.core.Koin;
import org.koin.core.logger.Level;
import org.koin.ext.StringUtil;
import java.io.*;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.function.BiConsumer;

public class PropertyRegistryExt {

    /**
     * Save properties values into PropertyRegister
     */
    public static void saveProperties(PropertyRegistry registry, Properties properties) {
        Koin _koin = registry.getKoin();
        if (_koin.getLogger().isAt(Level.DEBUG)) {
            _koin.getLogger().debug("load " + properties.size() + " properties");
        }

        Map<String, String> propertiesMapValues = new HashMap<>();
        Iterator<Object> iterator = properties.keySet().iterator();
        while (iterator.hasNext()) {
            String key = (String) iterator.next();
            propertiesMapValues.put(key, properties.getProperty(key));
        }

        propertiesMapValues.forEach(new BiConsumer<String, String>() {
            @Override
            public void accept(String k, String v) {
                registry.saveProperty(k, StringUtil.clearQuotes(v));
            }
        });
    }

    /**
     * Load properties from Property file
     *
     * @param fileName
     */
    public static void loadPropertiesFromFile(PropertyRegistry registry, String fileName) {

        Koin _koin = registry.getKoin();

        if (_koin.getLogger().isAt(Level.DEBUG)) {
            _koin.getLogger().debug("load properties from " + fileName);
        }
        URL resource = Koin.class.getResource(fileName);
        String content = null;
        if (resource != null) {
            InputStream inputStream = null;
            InputStreamReader isr = null;
            BufferedReader br = null;
            try {
                StringBuilder sb = new StringBuilder();
                inputStream = resource.openStream();
                isr = new InputStreamReader(inputStream, "UTF-8");
                br = new BufferedReader(isr);
                String data = br.readLine();
                while (data != null) {
                    sb.append(data);
                    data = br.readLine();
                }
                content = sb.toString();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (br != null) {
                    try {
                        br.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (isr != null) {
                    try {
                        isr.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        if (content != null) {
            if (_koin.getLogger().isAt(Level.INFO)) {
                _koin.getLogger().info("loaded properties from file:'$fileName'");
            }
            Properties properties = readDataFromFile(content);
            saveProperties(registry, properties);
        }
    }

    public static Properties readDataFromFile(String content) {
        Properties properties = new Properties();
        try {
            properties.load(new ByteArrayInputStream(content.getBytes()));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return properties;
    }

    /**
     * Load properties from environment
     */
    public static void loadEnvironmentProperties(PropertyRegistry registry) {
        Koin _koin = registry.getKoin();
        if (_koin.getLogger().isAt(Level.DEBUG)) {
            _koin.getLogger().debug("load properties from environment");
        }
        Properties sysProperties = System.getProperties();
        saveProperties(registry, sysProperties);

        Map<String, String> getenv = System.getenv();
        Properties sysEnvProperties = new Properties();
        sysEnvProperties.putAll(getenv);
        saveProperties(registry, sysEnvProperties);
    }
}
